#pragma once

#include "Connection.hpp"

class IOService : public Connection
{
public:
    IOService(Reactor *owner, uint16_t dist_port,uint32_t dist_ip,SockPtr sock)
        : _sock(sock),
          Connection(owner,dist_port,dist_ip)
    {
    }
    virtual int Fd()
    {
        return _sock->GetSockfd();
    }
    virtual void Recver()
    {
        UpdateTimestamp();//更新活跃时间

        while (true)
        {
            string in;
            // 读取内核接收缓冲区中的数据
            int n = _sock->Recv(in);
            if (n > 0)
            {
                LOG(LogLevel::WARNING) << "成功接收消息，sockfd: " << Fd() << ":\r\n"
                                       << Readbuff();
                // 把数据添加到用户接收缓冲区
                AppendsReadbuff(in);
            }
            else if (n == 0)
            {
                LOG(LogLevel::WARNING) << "客户端退出，sockfd: " << Fd();
                Excepter();
                return;
            }
            else
            {
                // 判断错误码
                if (errno == EAGAIN || errno == EWOULDBLOCK) // 内核缓冲区数据全部读取完毕
                {
                    string out;
                    auto hand = Owner()->HandleRequset();
                    // 把接收缓冲区中的数据交付给上层->获得序列化后的响应报文
                    if (hand != nullptr)
                    {
                        out = hand(Readbuff());
                    }
                    if (out.empty()) // 如果为空，表示没能获得序列化后的响应报文
                    {
                        LOG(LogLevel::WARNING) << "没能获取完整报文，sockfd: " << Fd();

                        return;
                    }
                    // 把序列化后的响应报文添加到这个连接自己的用户级发送缓冲区
                    AppendsWritebuff(out);

                    // 发送这个连接自己的用户级发送缓冲区中的数据

                    Sender();

                    return;
                }
                else if (errno == EINTR) // 被信号中断
                {
                    // 重新recv
                    continue;
                }
                else // 真的出现错误
                {
                    Excepter();
                    return;
                }
            }
        }
    }
    virtual void Sender()
    {
        UpdateTimestamp();//更新活跃时间
        
        while (true)
        {
            // 发送用户发送缓冲区中的数据
            int n = _sock->Send(Writebuff());
            if (n > 0)
            {
                LOG(LogLevel::WARNING) << "成功发送消息，sockfd: " << Fd() << ":\r\n"
                                       << Writebuff();

                // 从用户发送缓冲区中  删除  已经发送的数据
                RemoveWritebuff(n);
            }
            else if (n == 0) // 表示成功发送了0个字节，即用户发送缓冲区空了,但内核发送缓冲区不为满
            {
                LOG(LogLevel::WARNING) << "消息发送完毕，sockfd: " << Fd();
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK) // 内核发送缓冲区被放满了
                {
                    LOG(LogLevel::WARNING) << "内核缓冲区满了，sockfd: " << Fd();
                    break;
                }
                else if (errno == EINTR) // 被信号中断
                {
                    // 重新send
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        // 判断是否需要进行写事件关心

        // 如果用户发送缓冲区不为空，并且内核发送缓冲区为满
        if (!Writebuff().empty())
        {
            // 添加写事件关心
            Owner()->ModifyEvent(Fd(), (EPOLLIN | EPOLLOUT | EPOLLET));

            LOG(LogLevel::WARNING) << "添加写事件关心，sockfd: " << Fd();
        }
        else// 如果用户发送缓冲区为空，就代表内核缓冲区不为满了
        {
            // 取消写事件关心
            Owner()->ModifyEvent(Fd(), (EPOLLIN | EPOLLET));
        }
    }
    virtual void Excepter()
    {
        char error_buf[defalut_error_buff_size];
        strerror_r(errno, error_buf, sizeof(error_buf));
        LOG(LogLevel::WARNING) << "error: " << error_buf;

        // 调用Reactor的成员函数DeleteConnection
        Owner()->DleteConnection(Fd());
    }
    ~IOService()
    {
    }

private:
    SockPtr _sock;
};